
package com.x52im.rbchat.logic.contact;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.x52im.rbchat.logic.contact.model.FooterItemValue;
import com.x52im.rbchat.logic.contact.model.FriendItemValue;
import com.x52im.rbchat.logic.contact.model.HeaderItemValue;
import com.x52im.rbchat.logic.contact.viewholder.foot.FooterItemViewHolder;
import com.x52im.rbchat.logic.contact.viewholder.FriendItemViewHolder;
import com.x52im.rbchat.logic.contact.viewholder.head.HeaderItemViewHolder;
import com.x52im.rbchat.R;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;

public class FriendListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

    private final static String TAG = FriendListAdapter.class.getSimpleName();

    /** 以下常量定义，用于itemViewType，定义的结果只要能满足 {@link #getItemViewType(int)} 方法中的区分条件即可 */
    private static final int TYPE_CONTACT = 100;
    private static final int TYPE_FOOTER_START_INDEX = 200;

    protected Fragment fragment;

    protected List<FriendItemValue> users;
    protected List<HeaderValueWrapper> headerValues;
    protected List<FooterValueWrapper> footerValues;

    protected OnItemClickListener onItemClickListener;

    public FriendListAdapter(Fragment fragment) {
        super();
        this.fragment = fragment;
    }

    @NonNull
    @Override
    final public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder;
        View itemView;

        // header的viewHolder实例化
        if (viewType < TYPE_CONTACT) {
            HeaderValueWrapper wrapper = headerValues.get(viewType);
            itemView = LayoutInflater.from(fragment.getActivity()).inflate(wrapper.layoutResId, parent, false);
            try {
                Constructor constructor = wrapper.headerViewHolderClazz.getConstructor(Fragment.class, FriendListAdapter.class, View.class);
                viewHolder = (HeaderItemViewHolder) constructor.newInstance(fragment, this, itemView);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage(),  e);
                throw new RuntimeException("创建 header viewHolder 失败了", e.getCause());
            }
            itemView.setOnClickListener(v -> {
                if (onItemClickListener != null) {
                    onItemClickListener.onHeaderItemClick(viewHolder.getAdapterPosition());
                }
            });
        }
        // 好友item的viewHolder实例化
        else if (viewType == TYPE_CONTACT) {
            itemView = LayoutInflater.from(fragment.getActivity()).inflate(R.layout.contact_item_friend, parent, false);
            viewHolder = new FriendItemViewHolder(fragment, this, itemView);
            itemView.setOnClickListener(v -> {
                if (onItemClickListener != null) {
                    int position = viewHolder.getAdapterPosition();
                    onItemClickListener.onFriendItemClick(users.get(position - headerCount()));
                }
            });
        }
        // footer的viewHolder实例化
        else {
            FooterValueWrapper wrapper = footerValues.get(viewType - TYPE_FOOTER_START_INDEX);
            itemView = LayoutInflater.from(fragment.getActivity()).inflate(wrapper.layoutResId, parent, false);
            try {
                Constructor constructor = wrapper.footerViewHolderClazz.getConstructor(Fragment.class, FriendListAdapter.class, View.class);
                viewHolder = (FooterItemViewHolder) constructor.newInstance(fragment, this, itemView);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage(),  e);
                throw new RuntimeException("创建 footer viewHolder 失败了", e.getCause());
            }
            itemView.setOnClickListener(v -> {
                if (onItemClickListener != null) {
                    onItemClickListener.onFooterItemClick(viewHolder.getAdapterPosition() - headerCount() - userCount());
                }
            });
        }
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof FriendItemViewHolder) {
            ((FriendItemViewHolder) holder).onBind(users.get(position - headerCount()));
        } else if (holder instanceof HeaderItemViewHolder) {
            HeaderValueWrapper wrapper = headerValues.get(position);
            ((HeaderItemViewHolder) holder).onBind(wrapper.headerItemValue);
        } else if (holder instanceof FooterItemViewHolder) {
            FooterValueWrapper wrapper = footerValues.get(position - headerCount() - userCount());
            ((FooterItemViewHolder<FooterItemValue>) holder).onBind(wrapper.footerItemValue);
        }
    }

    @Override
    public int getItemViewType(int position) {
        // position处于头item的索引范围时
        if (position < headerCount()) {
            return position;
        }
        // position处于好友数据item的索引范围时
        else if ((position - headerCount()) < userCount()) {
            return TYPE_CONTACT;
        }
        // 余下的索引范围可以认为是footer索引范围
        else {
            return TYPE_FOOTER_START_INDEX + (position - headerCount() - userCount());
        }
    }

    @Override
    public int getItemCount() {
        return headerCount() + footerCount() + userCount();
    }

    public void addHeaderViewHolder(Class<? extends HeaderItemViewHolder> clazz, int layoutResId, HeaderItemValue value) {
        if (headerValues == null) {
            headerValues = new ArrayList<>();
        }
        int position = headerCount();
        headerValues.add(new HeaderValueWrapper(clazz, layoutResId, value));

        notifyItemInserted(position);
    }

    public void updateHeader(int index, HeaderItemValue value) {
        HeaderValueWrapper wrapper = headerValues.get(index);
        headerValues.set(index, new HeaderValueWrapper(wrapper.headerViewHolderClazz, wrapper.layoutResId, value));
        notifyItemChanged(index);
    }

    public void addFooterViewHolder(Class<? extends FooterItemViewHolder> clazz, int layoutResId, FooterItemValue value) {
        if (footerValues == null) {
            footerValues = new ArrayList<>();
        }
        footerValues.add(new FooterValueWrapper(clazz, layoutResId, value));
        notifyItemInserted(headerCount() + userCount() + footerCount());
    }

    public void updateFooter(int index, FooterItemValue value) {
        FooterValueWrapper wrapper = footerValues.get(index);
        footerValues.set(index, new FooterValueWrapper(wrapper.footerViewHolderClazz, wrapper.layoutResId, value));
        notifyItemChanged(headerCount() + userCount() + index);
    }

    public List<FriendItemValue> getUsers() {
        return users;
    }

    public int getContactCount() {
        return userCount();
    }

    public void setUsers(List<FriendItemValue> users) {
        this.users = users;
        notifyDataSetChanged();
    }

    public int headerCount() {
        return headerValues == null ? 0 : headerValues.size();
    }

    private int userCount() {
        return users == null ? 0 : users.size();
    }

    public int footerCount() {
        return footerValues == null ? 0 : footerValues.size();
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public interface OnItemClickListener {
        void onFriendItemClick(FriendItemValue userInfo);
        void onHeaderItemClick(int index);
        void onFooterItemClick(int index);
    }

    static class HeaderValueWrapper {
        Class<? extends HeaderItemViewHolder> headerViewHolderClazz;
        int layoutResId;
        HeaderItemValue headerItemValue;

        public HeaderValueWrapper(Class<? extends HeaderItemViewHolder> headerViewHolderClazz, int layoutResId, HeaderItemValue headerItemValue) {
            this.headerViewHolderClazz = headerViewHolderClazz;
            this.layoutResId = layoutResId;
            this.headerItemValue = headerItemValue;
        }
    }

    static class FooterValueWrapper {
        Class<? extends FooterItemViewHolder> footerViewHolderClazz;
        int layoutResId;
        FooterItemValue footerItemValue;

        public FooterValueWrapper(Class<? extends FooterItemViewHolder> footerViewHolderClazz, int layoutResId, FooterItemValue footerItemValue) {
            this.footerViewHolderClazz = footerViewHolderClazz;
            this.layoutResId = layoutResId;
            this.footerItemValue = footerItemValue;
        }
    }
}
